import sys 
from numpy import zeros, array


class Node:
    def __init__(self, node_id, number_of_degrees_of_freedom, \
                 coordinates=zeros(2)):
        self.node_id = node_id
        self.coordinates = coordinates
        self.number_of_degrees_of_freedom = number_of_degrees_of_freedom

        self.coordinate_system = 'cartesian'
        self.number_of_dimensions = coordinates.size
        self.mass = 0.0

        self.unbalanced_load = zeros(self.number_of_dimensions)
        self.trial_displacement = zeros(self.number_of_dimensions)
        self.trial_velocity = zeros(self.number_of_dimensions)
        self.trial_acceleration = zeros(self.number_of_dimensions)

        self.committed_displacement = zeros(self.number_of_dimensions)
        self.committed_velocity = zeros(self.number_of_dimensions)
        self.committed_acceleration = zeros(self.number_of_dimensions)

    def add_unbalanced_load(self, load_vector, factor=1.0):
        """
        Add unbalanced load to the load vector.
        load_vector.size must equal coordinates.size.
        """
        if load_vector.size != self.coordinates.size:
            print >> sys.stderr, "The dimension of the load vector must \
                                  be equal to the dimension of the \
                                  coordinates vector"
            sys.exit(1)
        else:
            self.unbalanced_load = self.unbalanced_load + load_vector * factor

    def commit(self):
        """
        Update the values of committed values of nodal
        acceleration, velocity, and displacement.
        """
        self.committed_displacement = self.trial_displacement
        self.committed_velocity = self.trial_velocity
        self.committed_acceleration = self.trial_acceleration

    def increment_trial_acceleration(self, acceleration_vector):
        if acceleration_vector.size != self.coordinates.size:
            print >> sys.stderr, "The dimension of the acceleration vector \
                                  must be equal to the dimension of the  \
                                  coordinates vector"
            sys.exit(1)
        else:
            self.trial_acceleration += acceleration_vector

    def increment_trial_displacement(self, displacement_vector):
        if displacement_vector.size != self.coordinates.size:
            print >> sys.stderr, "The dimension of the displacement vector \
                                  must be equal to the dimension of the \
                                  coordinates vector"
            sys.exit(1)
        else:
            self.trial_displacement += displacement_vector

    def increment_trial_velocity(self, velocity_vector):
        if velocity_vector.size != self.coordinates.size:
            print >> sys.stderr, "The dimension of the velocity vector must \
                                  ual to the dimension of the coordinates \
                                  vector"
            sys.exit(1)
        else:
            self.trial_velocity += velocity_vector

    def print_nodal_coordinates(self):
        print "Node ID: " + str(self.node_id)
        if self.coordinate_system == 'cartesian':
            print "x = " + str(self.coordinates[0])
            if self.coordinates.size > 1:
                print "y = " + str(self.coordinates[1])
            if self.coordinates.size > 2:
                print "z = " + str(self.coordinates[2])
        print ""

    def zero_unbalanced_load(self):
        self.unbalanced_load = 0.0

if __name__ == "__main__":
    print "1D"
    n = Node(1, coordinates=array([1.0]))
    n.print_nodal_coordinates()

    print "2D"
    n = Node(1, coordinates=array([1.0, 0.0]))
    n.print_nodal_coordinates()

    print "3D"
    n = Node(1, coordinates=array([1.0, 0.0, 0.0]))
    n.print_nodal_coordinates()
